# RssScreen - This screen displays RSS feeds
# Copyright (C) 2007 Lauri Taimila
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2007, Lauri Taimila"
__author__ = "Lauri Taimila <lauri@taimila.com>"

import os
import gtk
import pango
import clutter

from frontend.user_event import UserEvent
from frontend.gui.screens.screen import Screen
from frontend.gui.transitions.transition import Transition

# RSS Feed library
from frontend.medialibrary.feeds import Feed
from frontend.medialibrary.feeds import Entry
from frontend.medialibrary.feeds import FeedLibrary

# FeedEntry utils
from utils.feed_utils import FeedEntryParser

# Widgets
from frontend.gui.widgets.menu import Menu
from frontend.gui.widgets.selector import Selector
from frontend.gui.widgets.text_menu import TextMenu
from frontend.gui.widgets.text_menu_item import TextMenuItem
from frontend.gui.widgets.list_indicator import ListIndicator

class RssScreen(Screen):
    """
    RssScreen
    
    This screen displayes RSS-feeds from Feed library. Screen contains menu
    that includes all feed titles and number of entries per feed.
    """
    
    def __init__(self, ui, frontend, theme):
        """
        Initialize screen. Read data from FeedLibrary and create menu of feeds.
        @param ui: UserInterface object
        @param frontend: FrontendClient object
        @param theme: Theme object
        """
        self.group = clutter.Group()
        Screen.__init__(self, ui.STAGE_WIDTH, ui.STAGE_HEIGHT)
        
        self.feed_order = 'UNREAD' # Feeds ordered by number of unread entries
        self.active_menu = "feed"
        self.ui = ui
        self.frontend = frontend
        self.theme = theme
        self.library = frontend.get_feed_library()
        
        # Screen Title (Displayed at the bottom left corner)
        screen_title = clutter.Label()
        screen_title.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.13)) + "px")
        screen_title.set_color(self.theme.getColor("screentitle"))
        screen_title.set_text("Headlines")
        screen_title.set_name("screen_title")
        screen_title.set_position(self.ui.x(0), self.ui.y(0.87))
        screen_title.show()
        self.group.add(screen_title)
        
        # RSS Icon
        rss = gtk.gdk.pixbuf_new_from_file(self.theme.getImage("rss_icon"))
        icon = clutter.Texture()
        icon.set_pixbuf(rss)
        icon.set_position(self.ui.x(0.05), self.ui.y(0.07))
        icon.show()
        self.group.add(icon)
        
        # RSS Title
        title = clutter.Label()
        title.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0833)) + "px")
        title.set_color(clutter.Color(0xff, 0xff, 0xff, 0xff))
        title.set_text("RSS Feeds")
        title.set_position(self.ui.x(0.13), self.ui.y(0.07))
        title.show()
        self.group.add(title)
        
        # Display information box if there are not feeds available
        if self.library.is_empty() or len(self.library.get_feeds()) == 0:
            self._create_no_feeds_information()
        else:
            # Menus
            self._create_context_menu()
            self._create_feed_menu()
            self._create_feed_menu_indicator()
            self.menu.set_active(True)
            self.context_menu.set_active(False)
            
            # Feeds Title
            feeds_title = clutter.Label()
            feeds_title.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.04167)) + "px")
            feeds_title.set_color(self.theme.getColor("title"))
            feeds_title.set_text("Feeds")
            feeds_title.set_position(self.ui.x(0.3953), self.ui.y(0.2))
            feeds_title.show()
            self.group.add(feeds_title)
            
            # Unread Title
            unread_title = clutter.Label()
            unread_title.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.04167)) + "px")
            unread_title.set_color(self.theme.getColor("title"))
            unread_title.set_text("Unread")
            unread_title.set_position(self.ui.x(0.8053), self.ui.y(0.2))
            unread_title.show()
            self.group.add(unread_title)
            
            # Feed description text
            self.description = clutter.Label()
            self.description.set_line_wrap(False)
            self.description.set_ellipsize(pango.ELLIPSIZE_END)
            self.description.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.03646)) + "px")
            self.description.set_color(self.theme.getColor("text"))
            self.description.set_use_markup(True)
            self.description.set_text(FeedEntryParser().strip_tags(Feed(self.menu.get_current_menuitem().get_userdata()).get_description()))
            self.description.set_size(self.ui.x(0.5088), self.ui.y(0.0651))
            self.description.set_position(self.ui.x(0.3953), self.ui.y(0.9))
            self.description.show()
            self.group.add(self.description)
        
        self.group.show()
        self.ui.getStage().add(self.group)
    
    def _create_feed_menu(self):
        """
        Create Feed-menu. This menu contains list of Feeds. It also displays
        number of unread entries per feed.
        """
        self.menu = TextMenu(self.theme, self.frontend.get_configuration().show_effects())
        self.menu.set_row_count(1)
        self.menu.set_visible_column_count(7)
        self.menu.set_item_size(self.ui.x(0.5124), self.ui.y(0.0781))
        self.menu.set_position(self.ui.x(0.3807), self.ui.y(0.2604))        

        # Create menu items based on FeedLibrary
        feeds = self.library.get_feeds(self.feed_order)
        for feed in feeds:        
            unread = feed.get_number_of_unread()
            if unread == 0:
                unread = None
            else:
                unread = str(unread)
            item = TextMenuItem(self.ui.x(0.5124), self.ui.y(0.0781), self.theme, FeedEntryParser().strip_tags(feed.get_title()), unread)
            item.set_userdata(feed.get_feed_url())
            item.show()
            self.menu.add_actor(item)
        
        self.menu.show()
        self.group.add(self.menu)
    
    def _create_feed_menu_indicator(self):
        """
        Create a ListIndicator for feed menu.
        """
        self.li = ListIndicator(self.ui.x(0.1464), self.ui.y(0.04427), self.theme, ListIndicator.VERTICAL)
        self.li.set_position(self.ui.x(0.8858) - self.li.get_width(), self.ui.x(0.4649))
        self.li.set_delimiter(" | ")
        self.li.show()
        self.li.set_maximum(self.menu.get_number_of_items())
        self.li.set_current(1)
        self.group.add(self.li)
    
    def _create_context_menu(self):
        """
        Create RSS-feed context menu and add it to the screen.
        This menu contains buttons for update and sorting.
        """
        select = Selector(Selector.LARGE, self.theme)
        self.context_menu = Menu()
        
        self.context_menu.set_loop(True)
        item1 = TextMenuItem(self.ui.x(0.2196), self.ui.y(0.0781), self.theme, "Update feeds")
        self.context_menu.add(item1)
        item2 = TextMenuItem(self.ui.x(0.2196), self.ui.y(0.0781), self.theme, "Mark all as read")
        self.context_menu.add(item2)
        item3 = TextMenuItem(self.ui.x(0.2196), self.ui.y(0.0781), self.theme, "Sort by name")
        self.context_menu.add(item3)
        item4 = TextMenuItem(self.ui.x(0.2196), self.ui.y(0.0781), self.theme, "Sort by unread")
        self.context_menu.add(item4)
        
        self.context_menu.set_selector(select)
        self.context_menu.set_position(self.ui.x(0.0732), self.ui.y(0.2604))
        self.context_menu.set_active(False)
        self.context_menu.show_all() 
        self.group.add(self.context_menu)
            
    def _create_no_feeds_information(self):
        """
        Create textures and labels for information screen. This is displayed
        instead of feeds list if there are no feeds available. This screen helps
        users to add new feeds to the system.
        """
        # Create warning icon
        warning = gtk.gdk.pixbuf_new_from_file(self.theme.getImage("warning_icon"))
        warning_icon = clutter.Texture()
        warning_icon.set_pixbuf(warning)
        warning_icon.set_position(self.ui.x(0.2804), self.ui.y(0.2709))
        warning_icon.show()
        self.group.add(warning_icon)
    
        # Create warning title
        info_title = clutter.Label()
        info_title.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0625)) + "px")
        info_title.set_text("No headlines available!")
        info_title.set_position(self.ui.x(0.3367), self.ui.y(0.2709))
        info_title.set_color((255,255,255,255))
        info_title.show()
        self.group.add(info_title)
        
        # Create warning help text
        info = clutter.Label()
        info.set_text("""To use headlines you have to add some RSS feeds with content management tool. To do this, click 'Content' button located in toolbar. Select 'RSS feeds' tab and click 'Add' button. Now you can write RSS feed URL to textentry. You can get RSS feed URL from webpages that support RSS.""")
        info.set_size(self.ui.x(0.4685), self.ui.y(0.5208))
        info.set_position(self.ui.x(0.2855), self.ui.y(0.2416))
        info.set_line_wrap(True)
        info.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.0417)) + "px")
        info.set_color(self.theme.getColor("menuitem_inactive"))
        info.show()
        self.group.add(info)
    
    def update(self):
        """
        Update screen widgets. This is called always when screen is poped from
        the screen history.
        """
        #remove current feed menu, create a new one and set it to active
        self.group.remove(self.menu)
        self._create_feed_menu()
        self.menu.set_active(True)
    
    def get_group(self):
        """Return all actors of the screen."""
        return self.group
        
    def get_type(self):
        """Return screen type."""
        return Screen.NORMAL
    
    def get_name(self):
        """Return screen name (human readble)"""
        return "RssScreen"
    
    def handle_user_event(self, event):   
        """ 
        Handle screen specific user events
        @param event: UserEvent object
        """
        type = event.get_type()
        
        if type == UserEvent.NAVIGATE_UP:
            if self.active_menu == "feed":
                self.menu.move(TextMenu.UP)
                self.li.set_current(self.menu.get_current_postition() + 1) 
                feed = Feed(self.menu.get_current_menuitem().get_userdata())
                self.description.set_text(FeedEntryParser().strip_tags(feed.get_description()))
                self.description.set_size(self.ui.x(0.5088), self.ui.y(0.0651))
                #self.li.set_current(self.menu.get_current_postition() + 1)
            else:
                self.context_menu.scroll_up()
                
        elif type == UserEvent.NAVIGATE_DOWN:
            if self.active_menu == "feed":
                self.menu.move(TextMenu.DOWN)
                self.li.set_current(self.menu.get_current_postition() + 1) 
                feed = Feed(self.menu.get_current_menuitem().get_userdata())
                self.description.set_text(FeedEntryParser().strip_tags(feed.get_description()))
                self.description.set_size(self.ui.x(0.5088), self.ui.y(0.0651))
                #self.li.set_current(self.menu.get_current_postition() + 1)
            else:
                self.context_menu.scroll_down()
                
        # Make context active
        elif type == UserEvent.NAVIGATE_LEFT:
            if self.active_menu == "feed":
                self.active_menu = "context"
                self.li.hide_position()
                self.menu.set_active(False)
                self.description.hide()
                self.context_menu.set_active(True)
                
        # Make feed menu active
        elif type == UserEvent.NAVIGATE_RIGHT:
            if self.active_menu == "context":
                self.active_menu = "feed"
                self.li.show_position()
                self.menu.set_active(True)
                self.description.show()
                self.context_menu.set_active(False)
        
        # Menuitem selected (ENTER PRESSED)
        elif type == UserEvent.NAVIGATE_SELECT:
            if self.active_menu == "context":
                index = self.context_menu.get_current_postition()
                if index == 0:
                    #send message to bus and update screen
                    self.library.request_feed_update()
                    self.update()
                    print "update feeds"
                elif index == 1:
                    #tell feedlibrary to mark all as read and then update screen
                    self.library.mark_all_as_read()
                    self.update()
                    print "mark all read"
                elif index == 2:
                    #sort feeds by title ASC and update screen
                    self.feed_order = 'TITLE'
                    self.update()
                    print "sort title"
                elif index == 3:
                    #sort feeds by UNREAD DESC and update screen
                    self.feed_order = 'UNREAD'
                    self.update()
                    print "sort unread"
            else:
                # Feed selected from the menu. Change screen.
                feed = Feed(self.menu.get_current_menuitem().get_userdata())
                self.ui.changeScreen(self.ui.createScreen("feed", feed), 
                                       Transition.FORWARD)
